import { ActionNode } from '../BNode/ActionNode';
import { CustomNode } from '../BNode/CustomNode';
import { DelayNode } from '../BNode/DelayNode';
import { EventNode } from '../BNode/EventNode';
import { PromiseNode, WaitPromiseNode } from '../BNode/PromiseNode';
import { TweenNode } from '../BNode/TweenNode';
import { IfElse } from '../BTree/IfElse';
import { OptionTree } from '../BTree/OptionTree';
import { ParallelTree } from '../BTree/ParallelTree';
import { SelectTree } from '../BTree/SelectTree';
import { SequenceTree } from '../BTree/SequenceTree';
import { IEvent } from '../type/IEvent';

export namespace BTree {
    export function sequence(...events: IEvent[]) {
        const seq = new SequenceTree();
        seq.addChild(...events);
        return seq;
    }

    export function parallel(...events: IEvent[]) {
        const par = new ParallelTree();
        par.addChild(...events);
        return par;
    }

    export function select(...events: IEvent[]) {
        const select = new SelectTree();
        select.addChild(...events);
        return select;
    }

    export function option(...events: IEvent[]) {
        const opt = new OptionTree();
        opt.addChild(...events);
        return opt;
    }

    export function delay(time: number) {
        const node = new DelayNode(time);
        return node;
    }

    export function call(call: (blackboard?: any) => void) {
        const node = new ActionNode(call);
        return node;
    }

    export function tween(
        time: number,
        update: (ratio: number, dt: number, blackBoard?: any) => void,
        easing?: (n: number) => number
    ) {
        const node = new TweenNode(time, update, easing);
        return node;
    }

    export function check(
        rule: boolean,
        trueNode?: IEvent,
        falseNode?: IEvent
    ) {
        return new IfElse(rule, trueNode, falseNode);
    }

    export function custom(call?: (blackboard?: any) => void) {
        return new CustomNode(call);
    }

    export function promise(fn: () => Promise<any>) {
        return new PromiseNode(fn);
    }

    export function wait(p: Promise<any>) {
        return new WaitPromiseNode(p);
    }

    export function event(event: string) {
        return new EventNode(event);
    }
}
